package com.geline.easyexcel.config;

import cn.hutool.core.util.ClassUtil;
import com.geline.easyexcel.annotation.EasyExcelScan;
import com.geline.easyexcel.annotation.ExcelExportList;
import com.geline.easyexcel.annotation.ExcelExportPage;
import com.geline.easyexcel.annotation.ExcelImport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Class注册器：用于获取 @Table, @TableName实现EntityVO类
 * @author: mengxin
 * @date: 2023/9/23 9:58
 */
@Slf4j
public class EasyExcelRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

    //@ExcelImport-Map
    private static Map<String, Class> excelImportMap = new HashMap<>();
    //@ExcelExportPage-Map
    private static Map<String, Class> excelExportPageMap = new HashMap<>();
    //@ExcelExportList-Map
    private static Map<String, Class> excelExportListMap = new HashMap<>();

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes mapperScanAttrs = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(EasyExcelScan.class.getName()));
        if (mapperScanAttrs != null) {
            List<String> scanBasePackageSet = this.registerBeanDefinitions(metadata, mapperScanAttrs);
            log.info(">>>>>>>>> EasyExcel scanBasePackageSet = {}", scanBasePackageSet);
            for(String pck : scanBasePackageSet){
                registerBeanDefinitions(pck);
            }
        }
    }

    List<String> registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs) {
        List<String> basePackages = new ArrayList();
        basePackages.addAll(Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText).collect(Collectors.toList()));
        if (basePackages.isEmpty()) {
            basePackages.add(getDefaultBasePackage(annoMeta));
        }
        return basePackages;
    }

    public void registerBeanDefinitions(String basePackage){
        Set<Class<?>> importSet = ClassUtil.scanPackageByAnnotation(basePackage, ExcelImport.class);
        importSet.stream().forEach(row -> {
            ExcelImport annotation = row.getAnnotation(ExcelImport.class);
            String value = annotation.value();
            if(excelImportMap.get(value)!=null){
                log.error("found more @ExcelImport = {}", value);
            }
            this.excelImportMap.put(value, row);
        });
        log.info(">>>> success to scan {}, @ExcelImport = {}", basePackage, excelImportMap.size());

        Set<Class<?>> exportPageSet = ClassUtil.scanPackageByAnnotation(basePackage, ExcelExportPage.class);
        exportPageSet.stream().forEach(row -> {
            ExcelExportPage annotation = row.getAnnotation(ExcelExportPage.class);
            String value = annotation.value();
            if(excelExportPageMap.get(value)!=null){
                log.error("found more @ExcelExportPage = {}", value);
            }
            this.excelExportPageMap.put(value, row);
        });
        log.info(">>>> success to scan {}, @ExcelExportPage = {}", basePackage, excelExportPageMap.size());

        Set<Class<?>> exportListSet = ClassUtil.scanPackageByAnnotation(basePackage, ExcelExportList.class);
        exportListSet.stream().forEach(row -> {
            ExcelExportList annotation = row.getAnnotation(ExcelExportList.class);
            String value = annotation.value();
            if(excelExportListMap.get(value)!=null){
                log.error("found more @ExcelExportList = {}", value);
            }
            this.excelExportListMap.put(value, row);
        });
        log.info(">>>> success to scan {}, @ExcelExportList = {}", basePackage, excelExportListMap.size());
    }

    public static Class getImportRowClass(String code){
        return excelImportMap.get(code);
    }

    public static ExcelImport getExcelImport(String code){
        Class clazz = getImportRowClass(code);
        return (ExcelImport) clazz.getAnnotation(ExcelImport.class);
    }

    public static Class getExportRowClassByPage(String code){
        return excelExportPageMap.get(code);
    }

    public static Class getExportRowClassByList(String code){
        return excelExportListMap.get(code);
    }

    public static ExcelExportPage getExcelExportPage(String code){
        Class clazz = getExportRowClassByPage(code);
        return (ExcelExportPage) clazz.getAnnotation(ExcelExportPage.class);
    }

    public static ExcelExportList getExcelExportList(String code){
        Class clazz = getExportRowClassByList(code);
        return (ExcelExportList) clazz.getAnnotation(ExcelExportList.class);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
    }

    protected String getDefaultBasePackage(AnnotationMetadata metadata) {
        return ClassUtils.getPackageName(metadata.getClassName());
    }
}
